package lacus.wd_cinema.service;

import lacus.wd_cinema.dto.tickets.TicketBuyRequest;
import lacus.wd_cinema.dto.tickets.TicketBuyResponse;
import lacus.wd_cinema.entity.Screening;
import lacus.wd_cinema.entity.Ticket;
import lacus.wd_cinema.entity.User;
import lacus.wd_cinema.exception.EntityNotFoundException;
import lacus.wd_cinema.exception.OperationNotAllowedException;
import lacus.wd_cinema.repository.ScreeningRepository;
import lacus.wd_cinema.repository.TicketRepository;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 电影票业务处理类
 * @author lacus
 * @version 0.6
 * @since 0.6
 */
@Service
@Transactional
public class TicketService {
    private final TicketRepository ticketRepository;
    private final ScreeningService screeningService;
    private final ScreeningRepository screeningRepository;

    public TicketService(TicketRepository ticketRepository, ScreeningService screeningService, ScreeningRepository screeningRepository) {
        this.ticketRepository = ticketRepository;
        this.screeningService = screeningService;
        this.screeningRepository = screeningRepository;
    }

    public Ticket getTicketById(String ticketId) {
        return ticketRepository.findById(ticketId).orElseThrow(
                () -> new EntityNotFoundException("未找到ID为" + ticketId + "的电影票")
        );
    }

    /** 购买电影票 */
    public TicketBuyResponse buyTicket(
            TicketBuyRequest request, User purchaser) {
        Ticket ticket = new Ticket();
        BeanUtils.copyProperties(request, ticket);
        ticket.setOwner(purchaser);
        Screening screening = screeningService.getScreeningById(
                request.getScreeningId());
        for (Ticket t : screening.getTickets()) {
            if (t.isNotRefunded()
                    && t.getSeatRow() == ticket.getSeatRow()
                    && t.getSeatCol() == ticket.getSeatCol()) {
                throw new OperationNotAllowedException("(%d, %d)座位已被预订"
                        .formatted(ticket.getSeatRow(), ticket.getSeatCol()));
            }
        }
        Ticket ticketSaved = ticketRepository.save(ticket);
        screening.getTickets().add(ticket);
        ticket.setScreening(screening);
        screeningRepository.save(screening);
        return TicketBuyResponse.from(ticketSaved);
    }

    /** 退票服务 */
    public void refundTicket(String ticketId, User operator) {
        Ticket ticket = getTicketById(ticketId);
        if (!ticket.getOwner().equals(operator))
            throw new OperationNotAllowedException("操作者与持有者不一致");
        ticket.setStatus(Ticket.Status.REFUNDED);
        ticketRepository.save(ticket);
    }

    /**
     * 分页获取用户所拥有的所有电影票
     * @param owner 拥有者
     * @param page 页码
     * @param size 页的大小
     * @param status 票的状态
     * @return 页面内容
     */
    public Page<Ticket> getTickets(
            User owner, int page, int size, String status) {
        Pageable pageable = PageRequest.of(page, size);
        try {
            Ticket.Status ticketStatus = Ticket.Status.valueOf(status);
            return ticketRepository.findByOwnerAndStatus(owner, ticketStatus, pageable);
        } catch (IllegalArgumentException ignored) {
            return ticketRepository.findByOwner(owner, pageable);
        }
    }
}
